﻿#include "cquestion.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "QDebug"
#include "cimpques.h"
#include "csetting.h"

#include <QDir>
#include <QFileInfo>
#include <QTextCodec>
#include <QFileDialog>
#include <QSplitter>
#include <QDateTime>
#include <dialog/dialog_importsqlite.h>
#include <xml/cxmlparser.h>

QModelIndex MainWindow::s_qModelIndex;
MainWindow* MainWindow::sp_mainWindows = nullptr;
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 运行环境的初始化
    sp_mainWindows = this;
    CXMLParser::Init_CXMLParser();

    // 设置窗口名
    setWindowTitle(WINDOW_TITLE_MAINWINDOW);
    connect(this, SIGNAL(printRunningLog(QString)), this, SLOT(on_printRunningLog(QString)));

    // 前面是索引，后面是比例
    ui->splitter->setStretchFactor(0, 8);
    ui->splitter->setStretchFactor(1, 2);
    ui->splitter_2->setStretchFactor(0, 7);
    ui->splitter_2->setStretchFactor(1, 3);

#ifdef _N_MAC_
    ui->action_option->setMenuRole(QAction::PreferencesRole);
#endif
    // 增加一个sqlite数据库
    // 设置数据库文件的保存路径为程序运行路径下
    // 第一次使用addDatabase，
    // 后面获取数据库都用QSqlDatabase::database("qt_sql_default_connection")的方式来获取数据库对象。
    // 因为第二次用addDatabase会有警告。
    QSqlDatabase sqlDataBase = QSqlDatabase::addDatabase("QSQLITE");
    sqlDataBase.setDatabaseName(QCoreApplication::applicationDirPath() + "/" + FILE_NAME_QUES_SQLITE);
    sqlDataBase.close();

    // 初始化的工作
    // 主要负责开始界面的绘制和数据的显示
    // 右键菜单的逻辑
    init();
}

MainWindow::~MainWindow()
{
    delete ui;
}

/**
 * @brief 窗口运行时初始化的工作
 * 1. 题目信息表
 * 2. 右键
 */
void MainWindow::init()
{
    // 1. 初始化题目表的
    ui->tab_questions->setSelectionBehavior(QAbstractItemView::SelectRows);
    if  (p_questionsTable == nullptr)
    {
        p_questionsTable = new QStandardItemModel(this);
        p_questionsTable->setColumnCount(7);
        p_questionsTable->setHeaderData(0, Qt::Horizontal, TABCOLNAME_PROTECTIONPOSITION);
        p_questionsTable->setHeaderData(1, Qt::Horizontal, TABCOLNAME_DIFFICULTY        );
        p_questionsTable->setHeaderData(2, Qt::Horizontal, TABCOLNAME_INNERNUMBER       );
        p_questionsTable->setHeaderData(3, Qt::Horizontal, TABCOLNAME_FILEMD5           );
        p_questionsTable->setHeaderData(4, Qt::Horizontal, TABCOLNAME_FLAG              );
        p_questionsTable->setHeaderData(5, Qt::Horizontal, TABCOLNAME_KNOWLEDGEPOINTS   );
        p_questionsTable->setHeaderData(6, Qt::Horizontal, TABCOLNAME_FROMWHERE         );
    }
    ui->tab_questions->setModel(p_questionsTable);
    // 修改列宽
    ui->tab_questions->setColumnWidth(0, 60);
    ui->tab_questions->setColumnWidth(1, 30);
    ui->tab_questions->setColumnWidth(2, 60);
    ui->tab_questions->setColumnWidth(3, 260);
    ui->tab_questions->setColumnWidth(4, 300);
    // 最后一列自动扩展
    ui->tab_questions->horizontalHeader()->setStretchLastSection(true);



    QSqlDatabase db = QSqlDatabase::database("qt_sql_default_connection");
    // 创建表
    if (!CSQLManager::isTableExist(db, QUES_TABLE_NAME))
    {
        QString sql = "create table " + QUES_TABLE_NAME + "(";
        QString protectionPosition  = QUES_PROTECTIONPOSITION   + " text, ";
        QString difficulty          = QUES_DIFFICULTY           + " text, ";
        QString innerNumber         = QUES_INNERNUMBER          + " text, ";
        QString fileMd5             = QUES_FILEMD5              + " text primary key, ";
        QString flag                = QUES_FLAG                 + " text, ";
        QString knowledgePoints     = QUES_KNOWLEDGEPOINTS      + " text, ";
        QString fromWhere           = QUES_FROMWHERE            + " text";
        sql += protectionPosition + difficulty + innerNumber + fileMd5 + flag + knowledgePoints + fromWhere +")";
        CSQLManager::exec(db, sql);
    }
    db.close();
    // 从数据库中读取数据填充到界面上
    initQuestionTableFromDB();

    // 2. 初始化右键菜单
    pAct_exportQuestion = _menu_rightClick.addAction(QString::fromLocal8Bit("导出该题目"));
    pAct_reflushQuesLib = _menu_rightClick.addAction(QString::fromLocal8Bit("刷新题库"));
    ui->tab_questions->setContextMenuPolicy(Qt::CustomContextMenu); //注意
    connect(ui->tab_questions,SIGNAL(customContextMenuRequested(const QPoint &)),this,SLOT(onCustomContextMenuRequested(const QPoint&)));
    connect(pAct_exportQuestion, SIGNAL(triggered()), this, SLOT(onExportQuestion()));
    connect(pAct_reflushQuesLib, SIGNAL(triggered()), this, SLOT(onReflushQuesLib()));
}

// 从数据库中读取数据填充到界面上
void MainWindow::initQuestionTableFromDB()
{
    // 删除已有的数据
    p_questionsTable->removeRows(0, p_questionsTable->rowCount());

    // 数据库中数据的记录总数
    int questionsSize = CQuestion::getQuestionAcount();

    // 从数据库中获取所有的题目信息
    stQuestion *p_questionsBuffer = new stQuestion[questionsSize];
    CQuestion::getAllQuestions(p_questionsBuffer, questionsSize);

    // 显示到界面上
    for (int i = 0; i < questionsSize; i++)
    {
        QStandardItem* protectionPosition = new QStandardItem(p_questionsBuffer[i].protectionPosition);
        p_questionsTable->setItem(i, 0, protectionPosition);

        QStandardItem* difficulty = new QStandardItem(p_questionsBuffer[i].difficulty);
        p_questionsTable->setItem(i, 1, difficulty);

        QStandardItem* innerNumber = new QStandardItem(p_questionsBuffer[i].innerNumber);
        p_questionsTable->setItem(i, 2, innerNumber);

        QStandardItem* fileMd5 = new QStandardItem(p_questionsBuffer[i].fileMd5);
        p_questionsTable->setItem(i, 3, fileMd5);

        QStandardItem* flag = new QStandardItem(p_questionsBuffer[i].flag);
        p_questionsTable->setItem(i, 4, flag);

        QStandardItem* knowledgePoints = new QStandardItem(p_questionsBuffer[i].knowledgePoints);
        p_questionsTable->setItem(i, 5, knowledgePoints);

        QStandardItem* fromWhere = new QStandardItem(p_questionsBuffer[i].fromWhere);
        p_questionsTable->setItem(i, 6, fromWhere);

    }
}

// 相应鼠标右键
void MainWindow::onCustomContextMenuRequested(const QPoint &point)
{
    QModelIndex row = ui->tab_questions->indexAt(point);
    if(!row.isValid())
    {
        pAct_exportQuestion->setEnabled(false);
    }

    s_qModelIndex = row;
    _menu_rightClick.exec(QCursor::pos());
}

// 右键菜单【导出该题目】
void MainWindow::onExportQuestion()
{
    stSetting setting = CSetting::getSettingInstance();

    // 题目所在目录
    QString difficulty = p_questionsTable->item(s_qModelIndex.row(), 1)->text();
    QString innerNumber = p_questionsTable->item(s_qModelIndex.row(), 2)->text();
    QString quesFromDir = setting.dir_baseQuesLib + "/" + difficulty + "/" + innerNumber;

    // 导出的目录
    QString quesToDir = setting.dir_exportQues + "/" + difficulty + innerNumber;

    if(copyFiles_Folder2Folder(quesFromDir, quesToDir))
    {
#ifdef _N_Debug_
        qDebug() << "【MainWindow::onExportQuestion()】导出题目成功。";
#endif
        emit(printRunningLog(L8BStr("导出题目") + difficulty + innerNumber + L8BStr("成功。")));
    }
    else
    {
#ifdef _N_Debug_
        qDebug() << "【MainWindow::onExportQuestion()】导出题目失败。";
#endif
        // 提示对话框
        QMessageBox msg(this);
        msg.setWindowTitle(L8BStr("失败"));
        msg.setText(L8BStr("从") + quesFromDir + L8BStr("复制文件到") + quesToDir + L8BStr("失败。"));
        msg.setIcon(QMessageBox::Critical);
        msg.exec();
    }

    qDebug() << "row : " << s_qModelIndex.row();
}

// 右键菜单【刷新题库】
void MainWindow::onReflushQuesLib()
{
    initQuestionTableFromDB();
    emit(printRunningLog(L8BStr("题库已刷新")));
}

// 菜单栏【设置 > 选项option】
void MainWindow::on_action_option_triggered()
{
    CSetting *p_settingWindow = new CSetting();
    p_settingWindow->exec();
}

// 菜单栏【题库 > 导入新题】
void MainWindow::on_actionnew_ques_triggered()
{
    CImpQues impQues;
    impQues.exec();

    // 更新数据
    initQuestionTableFromDB();
    emit(printRunningLog(L8BStr("已更新题库")));
}

// 菜单栏【文件 > 导入数据库】从xml文件导入数据库
void MainWindow::on_action_importSqliteFromXML_triggered()
{
    DIALOG_ImportSQLite dialog;
    dialog.exec();

    // 更新数据
    initQuestionTableFromDB();
}

// 菜单栏【文件 > 导出数据库 > .xml】导出数据库为xml文件
void MainWindow::on_action_exportSqlite2XML_triggered()
{
    QString exportDir = CSetting::getSettingInstance().dir_baseQuesLib;
    QString qstr_exportDir = QFileDialog::getSaveFileName(this, L8BStr("导出数据库"), exportDir, L8BStr("*.xml"));
#ifdef _N_Debug_
    qDebug() << L8BStr("【MainWindow::on_action_exportSqlite2XML_triggered()】导出路径为：") << qstr_exportDir;
#endif
    // 题目的总数量
    int i_quesAcount = CQuestion::getQuestionAcount();
    stQuestion *pstQuestionBuffet = new stQuestion[i_quesAcount];
    int okNumber = CQuestion::getAllQuestions(pstQuestionBuffet, i_quesAcount);
    if (okNumber == i_quesAcount)
    {
        CXMLParser::writeQuesSQLite2File(pstQuestionBuffet, i_quesAcount, qstr_exportDir);
        emit(printRunningLog(L8BStr("已导出题目") + QString::number(okNumber) + L8BStr("题") ));
    }
    else
    {
#ifdef _N_Debug_
    qDebug() << L8BStr("【MainWindow::on_action_exportSqlite2XML_triggered()】从数据库中获取题目信息出错。");
#endif
        emit(printRunningLog(L8BStr("导出题目出错") ));
        return;
    }
}

void MainWindow::on_tab_questions_clicked(const QModelIndex &index)
{
    // 获取当前选中题目的路径
    // 路径为：设置中的基本路径+难度+编号
    stSetting setting = CSetting::getSettingInstance();
    int iRow = index.row();
    QString difficulty = p_questionsTable->item(iRow, 1)->text();
    QString innerNumber = p_questionsTable->item(iRow, 2)->text();

    QString findDir = setting.dir_baseQuesLib + "/" + difficulty + "/" + innerNumber + "/readme.txt";
#ifdef _N_Debug_
#endif
    qDebug() << L8BStr("【MainWindow::on_tab_questions_clicked】搜索文件：") << findDir;

    QFile f_readme(findDir);
    if (f_readme.exists())
    {
        f_readme.open(QIODevice::ReadOnly | QIODevice::Text);
        QByteArray bytes = f_readme.readAll();
        ui->edt_readme->setText(L8BStr(bytes));
        f_readme.close();
    }
    else
    {
        ui->edt_readme->setText("");
    }
}

void MainWindow::on_printRunningLog(QString log)
{
    QDateTime current_date_time = QDateTime::currentDateTime();
    QString current_date =current_date_time.toString("[yyyy.MM.dd hh:mm:ss.zzz]");
    ui->runningLog->append(current_date+log);
}
